/*************************************************
func: 封装socket 基础接口
author: zyh
date: 2024.4.16
**************************************************/
#ifndef _SOCKET_API_H_
#define _SOCKET_API_H_
 
#ifdef __cplusplus
extern "C" {
#endif
 
/*基础接口---------------------------------------------------------------------*/
 
/**
功能：创建并初始化socket
入参：
    socket_type：指明通信字节流类型，取值如：
            SOCK_STREAM：流式套接字（TCP方式）
            SOCK_DGRAM：数据包套接字（UDP方式）
            SOCK_RAM：原始套接字
    socket_protocol:  表示传输协议，常用的有 IPPROTO_TCP 和IPPROTO_UDP，分别表示 TCP 传输协议和 UDP 传输协议。通常设置为0 （IPPROTO_TCP）
    broadcast_flag：发送UDP数据时是否广播
出参：无
返回：成功返回socket描述符，失败-1
**/
int socket_init(int socket_type, int socket_protocol, int broadcast_flag);
 
//socket客户端初始化 返回：成功返回socket描述符，失败-1
int socket_client_init(int socket_type, int socket_protocol, int broadcast_flag, int bind_port);
 
//客户端连接服务端，返回：成功：0， 失败：-1
int socket_client_connect(int sockfd, char *server_ip, int server_port);
 
//socket服务端初始化 返回：成功返回socket描述符，失败-1
int socket_server_init(int socket_type, int socket_protocol, int broadcast_flag, const char *ip, int bind_port, int max_listen_backlog);
 
//监听文件描述符是否可读，返回0可读，返回-1 监听超时(不可读)或失败
int select_fd(int fd, int timeout_ms);
 
//将文件描述符默认的阻塞行为修改为非阻塞
int set_fd_nonblock(int fd);
 
/*
非阻塞模式下循环读取直到缓冲区没有数据可读为止
非阻塞模式下如果没有数据会返回，不会阻塞着读，因此需要循环读取直到缓冲区没有数据可读为止
返回：-1 出错，0  连接关闭，成功返回实际接收到字节数
*/
ssize_t socket_recv_again(int fd, void *buf, size_t count);
 
//确保写入n个字节，返回：-1 出错，0  连接关闭，成功返回实际字节数
ssize_t socket_sendn(int fd, const void *buf, size_t n);
 
/**
函数功能：socket非堵塞接收消息（select实现，如果存在大量客户端连接的情况下，文件描述符过多，则不适用）
入参：fd：串口文件描述符
	  buf：接收数据的缓冲区
	  len：缓冲区的大小
	  timeout_ms：超时时间，毫秒
出参：无
返回：成功返回实际接收的字节数，0已断开连接， -1失败，-2超时无数据可读
**/  
int socket_rcv_nonblock(int socket_fd, void *buf, int size, int timeout_ms);
 
 
#ifdef __cplusplus
}
#endif
 
#endif